package main_classes;

import handlers.*;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;

import log.Loger;

import common.classes.FileResponseThread;
import common.classes.Tray;


import configurator.*;

public class Server {
	private static Server server;
	private static ServerSocket serverSocket;
	private static String confFilePath;
	private static SettingOfServer settings;
	private static Handler firstHandler;
	private static Tray tray;
	private static String adminName;
	private static String adminPassword;
	private static boolean notStopped;
	private static boolean working;
	private static Loger loger;
	private static Vector<FileResponseThread> pool;
	
	private Server() {
		tray = new Tray();
		prepareServer("ServerData/configurator.xml");
	}
	
	private Server(String cFP) {
		confFilePath = cFP;
		tray = new Tray();
		prepareServer(confFilePath);
	}
	
	private static void prepareServer(String cFP) {
		adminName = "admin";
		adminPassword = "admin";
		notStopped = true;
		working = false;
		confFilePath = cFP;
		settings = (new Configurator(confFilePath)).getSettings();
		loger = new Loger("server", "server", "server");
		generateHandlers();
//		preparePool();
	}
	/*
	private static void preparePool() {
		pool = new Vector<FileResponseThread>(settings.getCountThreadPool());
		FileResponseThread th = null;
		if (settings.getCountThreadPool() > 0) {
			for (int i = 0; i < settings.getCountThreadPool(); i++, th = null) {
				th = new FileResponseThread();
				pool.addElement(th);
				(new Thread(th)).start();
			}
		}
	}*/
	
	public static Server getServer() {
		if (server == null) server = new Server("ServerData/configurator.xml");
		return server;
	}
	
	public static Server getServer(String cFP) {
		if (server == null) server = new Server(cFP);
		return server;
	}
	
	public static ServerSocket getServerSocket() throws IOException {
		serverSocket = new ServerSocket(settings.getPort());
		return serverSocket;
	}
	
	public static Loger getLoger() {
		return loger;
	}
	
	private static void generateHandlers() {
		Handler buff = new ErrorHandler(null);
		buff = new GetHandler(buff);
		if (settings.getServerType().equals("balancer"))
			buff = new LoadBallanserHandler(buff, settings.getSubsidiariesServers(), settings.getPersents());
		if (settings.getServerType().equals("redirection"))
			buff = new RedirectHandler(buff, settings.getRootPath(), settings.getSubsidiariesServers());
		if (settings.isSessionSupport())
			buff = new SessionHandler(buff);
		buff = new PostHandler(buff);
		buff = new ServerHandler(buff);
		buff = new SocketReaderHandler(buff);
		firstHandler = buff;
	}
	
	public void parseInputSocket(Socket socket) {
		if (socket != null)
			firstHandler.parseRequest(socket, null, null);
	}
	
	public static void start() {
		prepareServer(confFilePath);
		working = true;
	}
	
	public static void restart() {
		working = false;
		if (PortListener.getSocketGetter() != null)
			try {
				PortListener.getSocketGetter().close();
			} catch (IOException e) {
				System.err.println(e);
			} finally {
				prepareServer(confFilePath);
				try {
					PortListener.setSocketGetter(new ServerSocket(Server.getSettings().getPort()));
					working = true;
				} catch (IOException e) {
					System.err.println(e);
				}
		}
	}
	
	public static void stop() {
		working = false;
		notStopped = false;
		tray.removeIcon();
	}
	
	public static boolean isNotStopped() {
		return notStopped;
	}
	
	public static boolean isWorking() {
		return working;
	}

	public static String getAdminName() {
		return adminName;
	}

	public static String getAdminPassword() {
		return adminPassword;
	}
	
	public static SettingOfServer getSettings() {
		return settings;
	}
	
	public static Vector<FileResponseThread> getPool() {
		return pool;
	}
}
